﻿//--------------------------------------------------------------------------
// 
//  Copyright (c) Chili Software.  All rights reserved. 
// 
//  File: AnonymousTypeMappingProvider.cs
//
//  Description: Creates the type mapping for anonymous types.
// 
//--------------------------------------------------------------------------

using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using Chili.Opf3.Mapping.Providers;
using Chili.Opf3.Relations;

namespace Chili.Opf3.Linq
{
	/// <summary>
	/// Creates the type mapping for a persistent type by inspecting the attributes that are set
	/// on the members of the persistent type.
	/// </summary>
	public sealed class AnonymousTypeMappingProvider : ITypeMappingProvider
	{
		/// <summary>
		/// Returns the persistent attribute of the type or null if the type has no 
		/// <see cref="PersistentAttribute">PersistentAttribute</see>.
		/// </summary>
		/// <param name="type">Type investigated for the <see cref="PersistentAttribute">PersistentAttribute</see>.</param>
		public PersistentAttribute GetPersistentAttribute(Type type)
		{
			if (type == null)
				throw new ArgumentNullException("type");

			// Check if the class is generated by the compiler.
			if (!Attribute.IsDefined(type, typeof(CompilerGeneratedAttribute)))
				return null;

			// Make up a new persistent attribute.
			PersistentAttribute attribute = new PersistentAttribute();
			attribute.Rights = PersistentRights.Load;
			return attribute;
		}

		/// <summary>
		/// Returns the <see cref="FieldAttribute">FieldAttribute</see> for the given member. If the member is not mapped,
		/// null is returned.
		/// </summary>
		/// <param name="type">The persistent type that's mapping is created.</param>
		/// <param name="member">The member of the persistent type.</param>
		/// <returns>An instance of the <see cref="FieldAttribute">FieldAttribute</see> or null if the member is not mapped.</returns>
		public FieldAttribute GetMemberFieldAttribute(Type type, MemberInfo member)
		{
			if (!Attribute.IsDefined(type, typeof(CompilerGeneratedAttribute)))
				return null;

			// Check the member for being a field.
			if (member is FieldInfo)
			{
				// HACK: Get the actual member name!
				int start = member.Name.IndexOf("<");
				int end = member.Name.IndexOf(">");
				return new FieldAttribute(member.Name.Substring(start + 1, end - start - 1));
			}
			return null;
		}

		/// <summary>
		/// Returns the <see cref="RelationAttribute">RelationAttribute</see> for the given member. If the member does not
		/// have an attribute set, null is returned.
		/// </summary>
		/// <param name="type">The persistent type that's mapping is created.</param>
		/// <param name="member">The member of the persistent type.</param>
		/// <param name="relatedType">The related object's type.</param>
		/// <returns>An instance of the <see cref="RelationAttribute">RelationAttribute</see> or null if the member does not have
		/// an attribute set.</returns>
		public RelationAttribute GetMemberRelationAttribute(Type type, MemberInfo member, Type relatedType)
		{
			return null;
		}
	}
}
